#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>             /* exit() */
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "user.h"
#include "clienthandler.h"

user_list* clientList;
user_list* currentListEntry;

void initClientHandler()
{
	clientList = NULL;
	currentListEntry = NULL;
}

user_list* registerClient(int clientSocket)
{
	/* Creer l'utilisateur */
	user_t* currentUser = (user_t*) malloc(sizeof(user_t));
	
	/* L'enregistrer dans la table des utilisateurs */
	if (currentListEntry == NULL)
	{
		/* Premier utilisateur */
		clientList = (user_list*) malloc(sizeof(user_list));
		clientList->prev = NULL;
		currentListEntry = clientList;

	} else {
		currentListEntry->next = (user_list*) malloc(sizeof(user_list));
		currentListEntry->next->prev = currentListEntry;
		currentListEntry = clientList->next;
	}

	currentListEntry->user = currentUser;
	currentListEntry->next = NULL;
	
	currentUser->sock = clientSocket;
	currentUser->score = 0;
	
	return currentListEntry;
}

void unregisterClient(user_list* client)
{
	/* Supprimer l'utilisateur de la liste */
	if (client->prev == NULL)
	{
		printf("Premier\n");
		/* Premier utilisateur */
		clientList = client->next;
	} else {
		printf("Non Premier\n");
		client->prev->next = client->next;
	}
	
	if (currentListEntry == client)
	{
		/* L'utilisateur a supprimer est le dernier utilisateur connecte */
		currentListEntry = client->prev;
	}
	
	free(client);
}

int safeReceive(user_t* user, char* buffer) {
	int received = recv(user->sock, buffer, TAILLEBUFFER, 0);
	
	if (received > 0)
	{	
		/* On a recu un message */
		if (buffer[received - 2] == '\r')
		{
			buffer[received - 2] = '\0';
		} else if (buffer[received - 1] == '\n')
		{		
			buffer[received - 1] = '\0';
		} else {
			buffer[received] = '\0';
		}
	}
	return received;
}

int sendToUser(user_t* user, char* message)
{
	return send(user->sock, message, strlen(message), 0);
}

void
handleClient(void* userV)
{
	int ok;
    char buffer[TAILLEBUFFER];
    int received = -1;
	int loginCompleted = 0;
	
	user_list* userList = (user_list*) userV;
	user_t* user = userList->user;
	
	strcpy(buffer, "Connectez-vous.\n");
	send(user->sock, buffer, strlen(buffer), 0);

	/* Login */
	do {
	    if ((received = safeReceive(user, buffer)) < 0)
	    {
	        printf("Le message du client n'a pas pu être reçu.\n"); close(user->sock); pthread_exit(NULL);
	    }
	    
	    buffer[received] = '\0';
	    
	    /* Login recu */
	    
   		/* Verifier la longueur du login */
   		if (strlen(buffer) < 16)
   		{
   			strcpy(user->login, buffer);
   			
   			loginCompleted = 1;
   			strcpy(buffer, "Login réussi !\nBonjour, ");
   			strcpy(buffer + strlen(buffer), user->login);
   			strcpy(buffer + strlen(buffer), " !\n");
   		} else {
   			strcpy(buffer, "Login trop long. 15 caractères maxi.\n");
   		}
	   	
	   	send(user->sock, buffer, strlen(buffer), 0);
	} while (!loginCompleted);
	
    /* Fin login : utilisateur connecte */
    printf("%d: Connecté comme '%s'\n", user->sock, user->login);
    
    /* Mode de jeu */
    do
    {
		ok = 1;

	    /* Demander le mode de jeu */
	    sendToUser(user, "Sélectionner le mode de jeu :\nA = contre le serveur, B = devineur, C = maitre\n");
	    
	    received = safeReceive(user, buffer);
   
	    switch (buffer[0])
	    {
	    	case 'A': case 'a':
	    		/* Contre le serveur */
	    		contre_le_serveur(user);
	    		break;
	    		
	    	case 'B': case 'b':
	    		/* Devineur */
	    		devineur(user);
	    		break;
	    		
	    	case 'C': case 'c':
	    		/* Maitre */
	    		maitre(user);
	    		break;
	    		
    		default:
    			/* Reponse invalide */
    			ok = 0;
	    }
    } while(!ok);
    
    sendToUser(user, "Au revoir !\n");
    
    unregisterClient(userList);
    printf("%d : utilisateur déconnecté\n", user->sock);
    close(user->sock);
    free(user);
    pthread_exit(NULL);
}

void contre_le_serveur(user_t* user)
{}

void devineur(user_t* user)
{
	sendToUser(user, "En attente d'un adversaire...\n");
}

void maitre(user_t* user)
{
	char buffer[255];
	char combinaison[6];
	int received = -1;
	
	sendToUser(user, "Veuillez saisir la combinaison a deviner\n");
	received = safeReceive(user, buffer);
	
	strncpy(combinaison, buffer, 5);
	combinaison[5] = '\0'; /* Pour l'affichage */
	sendToUser(user, "La combinaison choisie est : ");
	sendToUser(user, combinaison);
	sendToUser(user, "\n");
	
	sendToUser(user, "En attente d'un adversaire...\n");
}